import CryptoJS from 'crypto-js';
import sysConfig from "@/config";
import {sm2} from 'sm-crypto';
import {SM4Util} from "sm4util"
import JSEncrypt from "jsencrypt";

const sm4 = new SM4Util()
const tool = {}

/* localStorage 操作方法 */
tool.data = {
	/**
	 * 设置本地存储数据
	 * @param {string} key - 存储键名
	 * @param {any} data - 存储的数据
	 * @param {number} datetime - 数据过期时间（秒）
	 */
	set(key, data, datetime = 0) {
		//根据系统配置选择是否使用AES加密
		if (sysConfig.LS_ENCRYPTION === "AES") {
			data = tool.crypto.AES.encrypt(JSON.stringify(data), sysConfig.LS_ENCRYPTION_key)
		}
		let cacheValue = {
			content: data,
			datetime: parseInt(datetime) === 0 ? 0 : new Date().getTime() + parseInt(datetime) * 1000
		}
		return localStorage.setItem(key, JSON.stringify(cacheValue))
	},
	/**
	 * 获取本地存储数据
	 * @param {string} key - 存储键名
	 * @returns {any} - 存储的数据
	 */
	get(key) {
		try {
			const value = JSON.parse(localStorage.getItem(key))
			if (value) {
				let nowTime = new Date().getTime()
				//检查数据是否过期
				if (nowTime > value.datetime && value.datetime !== 0) {
					localStorage.removeItem(key)
					return null;
				}
				//根据系统配置选择是否使用AES解密
				if (sysConfig.LS_ENCRYPTION === "AES") {
					value.content = JSON.parse(tool.crypto.AES.decrypt(value.content, sysConfig.LS_ENCRYPTION_key))
				}
				return value.content
			}
			return null
		} catch (err) {
			return null
		}
	},
	/**
	 * 移除本地存储数据
	 * @param {string} key - 存储键名
	 */
	remove(key) {
		return localStorage.removeItem(key)
	},
	/** 清空本地存储 */
	clear() {
		return localStorage.clear()
	}
}

/* sessionStorage 操作方法 */
tool.session = {
	/**
	 * 设置会话存储数据
	 * @param {string} table - 存储键名
	 * @param {any} settings - 存储的数据
	 */
	set(table, settings) {
		var _set = JSON.stringify(settings)
		return sessionStorage.setItem(table, _set);
	},
	/**
	 * 获取会话存储数据
	 * @param {string} table - 存储键名
	 * @returns {any} - 存储的数据
	 */
	get(table) {
		var data = sessionStorage.getItem(table);
		try {
			data = JSON.parse(data)
		} catch (err) {
			return null
		}
		return data;
	},
	/**
	 * 移除会话存储数据
	 * @param {string} table - 存储键名
	 */
	remove(table) {
		return sessionStorage.removeItem(table);
	},
	/** 清空会话存储 */
	clear() {
		return sessionStorage.clear();
	}
}

/* cookie 操作方法 */
tool.cookie = {
	/**
	 * 设置cookie
	 * @param {string} name - cookie名
	 * @param {string} value - cookie值
	 * @param {object} config - cookie配置
	 */
	set(name, value, config = {}) {
		var cfg = {
			expires: null,
			path: null,
			domain: null,
			secure: false,
			httpOnly: false,
			...config
		}
		var cookieStr = `${name}=${escape(value)}`
		//设置cookie过期时间
		if (cfg.expires) {
			var exp = new Date()
			exp.setTime(exp.getTime() + parseInt(cfg.expires) * 1000)
			cookieStr += `;expires=${exp.toGMTString()}`
		}
		//设置cookie路径
		if (cfg.path) {
			cookieStr += `;path=${cfg.path}`
		}
		//设置cookie域名
		if (cfg.domain) {
			cookieStr += `;domain=${cfg.domain}`
		}
		document.cookie = cookieStr
	},
	/**
	 * 获取cookie
	 * @param {string} name - cookie名
	 * @returns {string} - cookie值
	 */
	get(name) {
		var arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"))
		if (arr != null) {
			return unescape(arr[2])
		} else {
			return null
		}
	},
	/**
	 * 移除cookie
	 * @param {string} name - cookie名
	 */
	remove(name) {
		var exp = new Date()
		exp.setTime(exp.getTime() - 1)
		document.cookie = `${name}=;expires=${exp.toGMTString()}`
	}
}

/* Fullscreen 全屏操作 */
tool.screen = function (element) {
	var isFull = !!(document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement || document.fullscreenElement);
	if (isFull) {
		//退出全屏
		if (document.exitFullscreen) {
			document.exitFullscreen();
		} else if (document.msExitFullscreen) {
			document.msExitFullscreen();
		} else if (document.mozCancelFullScreen) {
			document.mozCancelFullScreen();
		} else if (document.webkitExitFullscreen) {
			document.webkitExitFullscreen();
		}
	} else {
		//进入全屏
		if (element.requestFullscreen) {
			element.requestFullscreen();
		} else if (element.msRequestFullscreen) {
			element.msRequestFullscreen();
		} else if (element.mozRequestFullScreen) {
			element.mozRequestFullScreen();
		} else if (element.webkitRequestFullscreen) {
			element.webkitRequestFullscreen();
		}
	}
}

/* 复制对象 */
tool.objCopy = function (obj) {
	return JSON.parse(JSON.stringify(obj));
}

/* 日期格式化 */
tool.dateFormat = function (date, fmt = 'yyyy-MM-dd hh:mm:ss') {
	date = new Date(date)
	var o = {
		"M+": date.getMonth() + 1,                 //月份
		"d+": date.getDate(),                    //日
		"h+": date.getHours(),                   //小时
		"m+": date.getMinutes(),                 //分
		"s+": date.getSeconds(),                 //秒
		"q+": Math.floor((date.getMonth() + 3) / 3), //季度
		"S": date.getMilliseconds()             //毫秒
	};
	if (/(y+)/.test(fmt)) {
		fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
	}
	for (var k in o) {
		if (new RegExp("(" + k + ")").test(fmt)) {
			fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
		}
	}
	return fmt;
}

/* 获取星期几 */
tool.getWeekDay = function (date) {
	let wk = date.getDay()
	let weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
	let week = weeks[wk]
	return week;
}

/* 千分符 */
tool.groupSeparator = function (num) {
	num = num + '';
	if (!num.includes('.')) {
		num += '.'
	}
	return num.replace(/(\d)(?=(\d{3})+\.)/g, function ($0, $1) {
		return $1 + ',';
	}).replace(/\.$/, '');
}

// 下划线转换驼峰
tool.toHump = function (name) {
	return name.replace(/\_(\w)/g, function (all, letter) {
		return letter.toUpperCase();
	});
}

// 驼峰转换下划线
tool.toLine = function (name) {
	return name.replace(/([A-Z])/g, "_$1").toLowerCase();
}

/* 常用加解密 */
tool.crypto = {
	//MD5加密
	MD5(data) {
		return CryptoJS.MD5(data.trim()).toString()
	},
	//BASE64加解密
	BASE64: {
		//加密
		encrypt(data) {
			return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(data))
		},
		//解密
		decrypt(cipher) {
			if (cipher != undefined && cipher != null && cipher != '') {
				return CryptoJS.enc.Base64.parse(cipher).toString(CryptoJS.enc.Utf8)
			} else {
				return "";
			}
		}
	},
	//AES加解密
	AES: {
		//加密
		encrypt(data, secretKey, config = {}) {
			if (secretKey.length % 8 != 0) {
				console.warn("[CyOa error]: 秘钥长度需为8的倍数，否则解密将会失败。")
			}
			const result = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(secretKey), {
				iv: CryptoJS.enc.Utf8.parse(config.iv || ""),
				mode: CryptoJS.mode[config.mode || "ECB"],
				padding: CryptoJS.pad[config.padding || "Pkcs7"]
			})
			return result.toString()
		},
		//解密
		decrypt(cipher, secretKey, config = {}) {
			const result = CryptoJS.AES.decrypt(cipher, CryptoJS.enc.Utf8.parse(secretKey), {
				iv: CryptoJS.enc.Utf8.parse(config.iv || ""),
				mode: CryptoJS.mode[config.mode || "ECB"],
				padding: CryptoJS.pad[config.padding || "Pkcs7"]
			})
			return CryptoJS.enc.Utf8.stringify(result);
		}
	},
	//数据加密转换
	convertData(cipher) {
		if (cipher != undefined && cipher != null && cipher != '') {
			if (sysConfig.DATA_ENCRYPT_MODE == '1') {
				return this.AES.decrypt(cipher, sysConfig.DATA_ENCRYPT_KEY);
			} else {
				return "";
			}
		} else {
			return "";
		}
	},
	//参数加密转换
	convertParam(str) {
		if (str != undefined && str != null && str != '') {
			if (sysConfig.DATA_ENCRYPT_MODE == '1') {
				return this.AES.encrypt(str, sysConfig.DATA_ENCRYPT_KEY);
			} else {
				return "";
			}
		} else {
			return "";
		}
	},
	//SM2加解密
	SM2: {
		//加密
		encrypt(data) {
			let cipherMode = 1;
			let publicKey = tool.data.get("PUBLIC_KEY");
			return sm2.doEncrypt(data, publicKey, cipherMode);
		},
		//解密
		decrypt(data) {
			let cipherMode = 1;
			let privateKey = tool.data.get("PRIVATE_KEY");
			return sm2.doDecrypt(data, privateKey, cipherMode);
		}
	},
	//RSA加解密
	RSA: {
		//加密
		encrypt(data) {
			let jse = new JSEncrypt();
			let publicKey = tool.data.get("PUBLIC_KEY");
			jse.setPrivateKey(publicKey)
			return jse.encrypt(data);
		},
		//解密
		decrypt(data) {
			let jse = new JSEncrypt();
			let privateKey = tool.data.get("PRIVATE_KEY");
			jse.setPrivateKey(privateKey)
			return jse.decrypt(data);
		}
	},
	//对参数进行加密，同时对加密后值进行MD5签名，方便后台对参数密文进行校验
	createParam(param){
		let ep = sm4.encryptCustom_ECB(param, sysConfig.SM4_PRIVATE_KEY)
		return this.MD5(ep)+ep;
	},
	//对后台返回的密文结果进行解密
	convertResult(result){
		return sm4.decryptCustom_ECB(result, sysConfig.SM4_PRIVATE_KEY);
	}
}

export default tool
